package com.fisherman.ext;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @User: fisherman
 * @Date: 2020/5/28 9:34
 *
 * 拓展原理：
 *  Bean
 *  BeanFactoryPostProcessor ：bean的后置处理器，bean创建对象初始化前后进行拦截工作的
 *  BeanFactoryPostProcessor：beanFactory的后置处理器
 *      在beanFactory标注初始化之后调用，所有的bean配置已经保存加载到beanFactory，但是bean的实例化还没有创建
 *
 *  1.ioc容器创建对象
 *  2.invokeBeanFactoryPostProcessors(beanFactory)执行BeanFactoryPostProcessors
 *          如何找到所有的BeanFactoryPostProcessors并执行他们的方法
 *                  1.直接BeanFactory中找到所有类型是BeanFactoryPostProcessor的组件，并执行他们方法
 *                  2.在初始化创建其他组件前面
 *  2.BeanDefinitionRegistryPostProcessor  extends BeanFactoryPostProcessor
 *      postProcessBeanDefinitionRegistry();
 *      在所有bean定义信息将要被加载，bean实例还未创建
 *
 *      优先于BeanFactoryPostProcessor执行，
 *      利用BeanDefinitionRegistryPostProcessor给容器中再添加一些组件；
 *
 * 原理
 *      1.ioc创建对象
 *      2.refresh()-》invokeBeanFactoryPostProcessors(beanFactory)
 *      3.从容器中获取到所有的BeanDefinitionRegistryPostProcessor组件，一次触发所有的
 *          1.依次触发所有的postProcessBeanDefinitionRegistry()方法
 *          2.再来触发postProcessBeaFactory()方法BeanFactoryPostProcessor
 *      4.再来从容器中找到BeanFactoryPostProcessor组件，然后依次触发postProcessBeanFactor
 *
 *  3.ApplicationListener：监听容器中发布的事件，事件驱动模型开发
 *          public interface ApplicationListener<E extends ApplicationEvent>
 *      监听ApplicationEvent及其下面的子事件
 *
 * 步骤：
 *      1.写一个监听器监听某个事件（ApplicationEvent以及子类）
 *              @EventListener
 *                  原理：使用EventListenerMethodProcessor处理来处理来解析方法上的@EventListener
 *
 *      2.把监听器加入到容器
 *      3.只要容器中有相关事件发布，我们就监听这个事件
 *              ContextRefreshedEvent:容器刷新完成（所有bean都完全创建）会发布这个事件
 *              ContextClosedEvent：关闭容器会发布这个事件
 *      4.发布一个事件
 *
 * 原理：
 *      ContextRefreshedEvent,IOCTest_Tex$1[source=我发布时间],ContextClosedEvent
 *      1.ContextRefreshedEvent事件：
 *          1.容器创建对象：refresh()
 *          2.finishRefresh()容器刷新完成会发布ContextRefreshedEvent事件
 *      2.自己发布事件
 *      3.容器关闭会发布ContextClosedEvent
 *          【事件发布流程】
 *          3.publishEvent(new ContextRefreshedEvent(this))
 *                 事件发布流程
 *                      1.获取事件的多播器（派发起） getApplicationEventMulticaster()
 *                      2.multicastEvent派发事假
 *                      3.获取到所有ApplicationListener
 *                             for(final ApplicationListener<?>listener:getApplicationListeners(event,type))
 *                             1.如果有Executor，可以支持使用Executor进行异步派送
 *                                  Executor executor = getTaskExecutor();
 *                             2.否则，同步的方式直接执行listener方法：invokeListener(listener,event)
 *                             拿到listener回调onApplicationEvent方法
 *
 *   【事件多播器（派发器）】
 *          1.容器创建对象：refresh()
 *          2.initApplicationEventMulticaster();初始化ApplicationEventMulticaster；
 *              1.先去容器中找有没有id=“applicationEventMulticaster”的组价
 *              2.如果没有this.applicationEventMulticaster
 *                     并且加入到容器中，我们就可以在其他组价要派发事件，自动注入这个applicationEventMulticaster
 *    【容器中有哪些监听器】
 *          1.容器创建对象：refresh()
 *          2.registerListeners()
 *              从容器中拿到所有的监听器，把他们注册到applicationEventMulticaster中
 *              String[]listenerBeanNames =getBeanNamesForType(ApplicationListener.class,true,false)
 *               //listener注册到applicationEventMulticaster中
 *              getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName)
 *
 *      SmartInitializingSingleton原理 -》afterSingletonsInstantiated()
 *              1.ioc容器创建对象并refresh()
 *              2.finishBeanFactoryInitialization(beanFactory)初始化剩下的单实例bean
 *                  1.先创建所有的但实例化bean；getBean();
 *                  2.获取所有创建好的单实例bean，判断是否是SmartInitializingSingleton类型的
 *                  如果是就调用afterSingletonsInstantiated()
 */
@ComponentScan("com.fisherman.ext")
@Configuration  //告诉spring这是个配置类
public class ExtConfig {
}
